import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.channels.FileChannel;
import java.util.Iterator;
import org.mozilla.universalchardet.UniversalDetector;

public class ManipuladorDeArquivos implements Iterable<String> {

	private class FileIterator implements Iterator<String> {

		private String _currentLine;

		@Override
		public boolean hasNext() {
			try {
				_currentLine = _reader.readLine();
			} catch (Exception ex) {
				_currentLine = null;
				ex.printStackTrace();
			}

			return _currentLine != null;
		}

		@Override
		public String next() {
			return _currentLine;
		}

		@Override
		public void remove() {
		}
	}

	public static void atualizarDadoArquivo(String arquivoFonte, String caminhoCompletoArquivo, String dadoAtual, String dadoNovo) {
		ManipuladorDeArquivos leitorDeArquivos = null;
		StringBuilder output = new StringBuilder();
		try {
			leitorDeArquivos = new ManipuladorDeArquivos(arquivoFonte);
			for (String linha: leitorDeArquivos) {
				if (linha.equals(dadoAtual)) {
					linha = dadoNovo;
				}
				output.append(linha + "\r\n");
			}
			leitorDeArquivos.salvarArquivo(caminhoCompletoArquivo, output.toString());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (leitorDeArquivos != null) {
				leitorDeArquivos.close();
			}
			output = null;
		}

	}

	public static void copiarArquivo(String nomeArquivoOrigem, String nomeArquivoDestino) {
		FileInputStream fis;
		try {
			fis = new FileInputStream(nomeArquivoOrigem);
			FileOutputStream fos = new FileOutputStream(nomeArquivoDestino);
			FileChannel inChannel = fis.getChannel();
			FileChannel outChannel = fos.getChannel();
			outChannel.transferFrom(inChannel, 0, inChannel.size());
			outChannel.close();
			inChannel.close();
			fos.close();
			fis.close();
			outChannel = null;
			inChannel = null;
			fos = null;
			fis = null;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void excluirArquivo(String caminhoNomeArquivo) throws IOException {
		File fl = new File(caminhoNomeArquivo);
		if (fl.exists()) {
			fl.delete();
		}
		fl = null;
	}

	public static String getEncoddigArquivo(InputStream arquivo) throws IOException {
		byte[] buf = new byte[4096];

		// (1)
		UniversalDetector detector = new UniversalDetector(null);

		// (2)
		int nread;
		while (((nread = arquivo.read(buf)) > 0) && !detector.isDone()) {
			detector.handleData(buf, 0, nread);
		}
		arquivo.close();
		buf = null;
		// (3)
		detector.dataEnd();

		// (4)
		String encoding = detector.getDetectedCharset();
		// (5)
		detector.reset();
		detector = null;
		if (encoding != null) { return encoding; }
		return "ISO-8859-1";
	}

	public static void salvarArquivo(String caminhoNomeArquivo, byte[] output) throws FileNotFoundException, IOException {
		FileOutputStream fout = new FileOutputStream(caminhoNomeArquivo);
		fout.write(output);
		fout.close();
	}

	public static void salvarArquivo(String caminhoNomeArquivo, String output) throws IOException {
		File fl = new File(caminhoNomeArquivo);
		if (fl.exists()) {
			fl.delete();
		}
		fl.createNewFile();
		FileWriter fw = new FileWriter(fl);
		fw.write(output);
		fw.flush();
		fw.close();
		fw = null;
		fl = null;
	}

	public static void salvarArquivoParcial(String caminhoNomeArquivo, String output) throws IOException {
		File fl = new File(caminhoNomeArquivo);
		if (!fl.exists()) {
			fl.createNewFile();
		}
		FileWriter fw = new FileWriter(fl, true);
		fw.write(output);
		fw.flush();
		fw.close();
		fw = null;
		fl = null;
	}

	private BufferedReader _reader;

	public ManipuladorDeArquivos(String filePath) throws FileNotFoundException, UnsupportedEncodingException, IOException {
		_reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), getEncoddigArquivo(filePath)));
	}

	public void close() {
		try {
			_reader.close();
			_reader = null;
		} catch (Exception ex) {}
	}

	public String getEncoddigArquivo(String nomeArquivo) throws IOException {
		byte[] buf = new byte[4096];
		java.io.FileInputStream fis = new java.io.FileInputStream(nomeArquivo);

		// (1)
		UniversalDetector detector = new UniversalDetector(null);

		// (2)
		int nread;
		while (((nread = fis.read(buf)) > 0) && !detector.isDone()) {
			detector.handleData(buf, 0, nread);
		}
		fis.close();
		fis = null;
		buf = null;
		// (3)
		detector.dataEnd();

		// (4)
		String encoding = detector.getDetectedCharset();
		// (5)
		detector.reset();
		detector = null;
		if (encoding != null) { return encoding; }
		return "ISO-8859-1";
	}

	@Override
	public Iterator<String> iterator() {
		return new FileIterator();
	}
}
